package com.smedi.ismedi.web.starter.util;

import com.github.dozermapper.core.Mapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.File;
import java.lang.reflect.Field;
import java.util.*;

/**
 * @Author: xulinjun
 * @Date: 2021-6-3 14:48
 */
@Slf4j
@Component
public class DozerUtil {
    @Autowired
    Mapper mapper;

    /**
     * 解决泛型转换，请确保字段名称一致
     *
     * @param source
     * @param clz
     * @param <S>
     * @param <T>
     * @return
     */
    public <S, T> T mapGeneric(S source, Class<T> clz) {
        Class sourceClass = source.getClass();
        Field[] sourceFields = sourceClass.getDeclaredFields();
        Field[] targetFields = clz.getDeclaredFields();

        try {
            T target = clz.newInstance();
            for (Field sourceField : sourceFields) {
                Optional<Field> optional = Arrays.stream(targetFields).filter(field -> field.getName().equals(sourceField.getName())).findFirst();

                if (optional.isPresent()) {
                    Field targetField = optional.get();
                    sourceField.setAccessible(true);
                    targetField.setAccessible(true);
                    try {
                        if (!(sourceField.get(source) == null)) {
                            if (targetField.getType() == List.class) {
                                List<T> list = new ArrayList<>();
                                List<S> sourceList = (List<S>) sourceField.get(source);

                                for (S s : sourceList) {
                                    list.add(mapGeneric(s, clz));
                                }

                                targetField.set(target, list);
                            } else {
                                targetField.set(target, (T) sourceField.get(source));
                            }
                        }
                    } catch (IllegalArgumentException | IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
            }

            return target;
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * List  实体类 转换器
     *
     * @param source 原数据
     * @param clz    转换类型
     * @param <T>
     * @param <S>
     * @return
     */
    public <T, S> List<T> convertor(List<S> source, Class<T> clz) {
        if (source == null) return null;
        List<T> map = new ArrayList<>();
        for (S i : source) {
            if (i != null) {
                map.add(mapper.map(i, clz));
            }
        }
        return map;
    }

    /**
     * Set 实体类 深度转换器
     *
     * @param source 原数据
     * @param clz    目标对象
     * @param <T>
     * @param <S>
     * @return
     */
    public <T, S> Set<T> convertor(Set<S> source, Class<T> clz) {
        if (source == null) return null;
        Set<T> set = new TreeSet<>();
        for (S i : source) {
            if (i != null) {
                set.add(mapper.map(i, clz));
            }
        }
        return set;
    }

    /**
     * 实体类 深度转换器
     *
     * @param source
     * @param clz
     * @param <T>
     * @param <S>
     * @return
     */
    public <T, S> T convertor(S source, Class<T> clz) {
        if (source == null) return null;
        return mapper.map(source, clz);
    }

    public void convertor(Object source, Object object) {
        mapper.map(source, object);
    }

    public <T> void copyConvertor(T source, Object object) {
        mapper.map(source, object);
    }
}
